﻿using System;
using System.Web.UI;
using System.Collections.Generic;

namespace MyLib.Web {
	/// <summary>
	/// 
	/// </summary>
	public static class ControlExtensions {
		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="control"></param>
		/// <param name="id"></param>
		/// <returns></returns>
		public static T FindDescendantControl<T>(this System.Web.UI.Control control, string id) where T : System.Web.UI.Control, new() {
			if (control == null)
				throw new ArgumentNullException("control");

			if (string.IsNullOrWhiteSpace(id))
				throw new ArgumentNullException("name");

			T t;

			if (control.Page is MyPage) {
				var ck = control.UniqueID + "." + id;

				if (((MyPage)control.Page).m_cachedDescendantControls.ContainsKey(ck)) {
					t = (T)((MyPage)control.Page).m_cachedDescendantControls[ck];
				} else {
					t = (T)FindDescendantControl(control, id);
					if (t == null) {
						t = new T();
					}
				}

				((MyPage)control.Page).m_cachedDescendantControls[ck] = t;
			} else {
				t = (T)FindDescendantControl(control, id);
				if (t == null) {
					t = new T();
				}
			}

			return t;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="control"></param>
		/// <param name="id"></param>
		/// <returns></returns>
		private static System.Web.UI.Control FindDescendantControl(System.Web.UI.Control control, string id) {
			System.Diagnostics.Debug.Assert(control != null);
			System.Diagnostics.Debug.Assert(!string.IsNullOrWhiteSpace(id));

			Control ctrl0;

			ctrl0 = control.FindControl(id);
			if (ctrl0 != null) {
				return ctrl0;
			}

			Queue<Control> queue = new Queue<Control>();
			foreach (Control ctrl in control.Controls) {
				queue.Enqueue(ctrl);
			}

			while (queue.Count != 0) {
				var ctrl = queue.Dequeue();

				if (ctrl is INamingContainer) {
					ctrl0 = ctrl.FindControl(id);
					if (ctrl0 != null) {
						return ctrl0;
					}
				}

				foreach (Control ch in ctrl.Controls) {
					queue.Enqueue(ch);
				}
			}

			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="control"></param>
		/// <param name="id"></param>
		/// <returns></returns>
		public static T FindSiblingControl<T>(this System.Web.UI.Control control, string id) where T : System.Web.UI.Control {
			if (control == null)
				throw new ArgumentNullException("control");

			if (string.IsNullOrWhiteSpace(id))
				throw new ArgumentNullException("name");

			return (T)FindSiblingControl(control, id);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="control"></param>
		/// <param name="id"></param>
		/// <returns></returns>
		private static System.Web.UI.Control FindSiblingControl(System.Web.UI.Control control, string id) {
			System.Diagnostics.Debug.Assert(control != null);
			System.Diagnostics.Debug.Assert(!string.IsNullOrWhiteSpace(id));

			if (control.NamingContainer == null) {
				return FindDescendantControl(control.Page, id);
			} else {
				return FindDescendantControl(control.NamingContainer, id);
			}
		} // end of FindSiblingControl.
	} // end of ControlExtensions.
}
